package com.xhj.mybatis.reflection;

import com.xhj.mybatis.util.MapUtil;
import com.xhj.mybatis.reflection.invoker.*;
import com.xhj.mybatis.reflection.property.PropertyNamer;

import java.lang.reflect.*;
import java.text.MessageFormat;
import java.util.*;

/**
 * Reflector
 *
 * @author XJks
 * @description 反射器 Reflector 类用于缓存和分析一个类的属性、getter/setter方法、字段等信息，方便后续通过属性名快速获取对应的读写方法或字段。
 * <p>
 * TODO:
 *  主要作用是针对某个 Class<?> 的可反射视图缓存：
 *      1.预解析并缓存：
 *          1.1 所有 getter/setter 的方法名→Invoker
 *          1.2 属性名→类型（getGetterType/getSetterType）
 *          1.3 是否有默认构造器
 *      2.解决方法重载/桥接方法/字段直访等问题。
 */
public class Reflector {

    /**
     * 目标类的 Class 对象
     */
    private final Class<?> type;

    /**
     * 可读属性名数组（有 getter 方法或可直接访问字段）
     */
    private final String[] readablePropertyNames;

    /**
     * 可写属性名数组（有 setter 方法或可直接访问字段）
     */
    private final String[] writablePropertyNames;

    /**
     * 属性名到 setter 方法/字段写入器的映射
     */
    private final Map<String, Invoker> setMethods = new HashMap<>();

    /**
     * 属性名到 getter 方法/字段读取器的映射
     */
    private final Map<String, Invoker> getMethods = new HashMap<>();

    /**
     * 属性名到 setter 参数类型的映射
     */
    private final Map<String, Class<?>> setTypes = new HashMap<>();

    /**
     * 属性名到 getter 返回值类型的映射
     */
    private final Map<String, Class<?>> getTypes = new HashMap<>();

    /**
     * 目标类的无参构造方法（如果有）
     */
    private Constructor<?> defaultConstructor;

    /**
     * 属性名（大写）到实际属性名的映射，实现属性名大小写不敏感查找
     */
    private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();

    /**
     * 构造方法，初始化 Reflector，分析目标类的属性和方法
     *
     * @param clazz 目标类
     */
    public Reflector(Class<?> clazz) {
        // 记录目标类的 Class 对象
        type = clazz;
        // 查找并记录目标类的无参构造方法（如果有）
        addDefaultConstructor(clazz);
        // 查找并记录所有 getter 方法
        addGetMethods(clazz);
        // 查找并记录所有 setter 方法
        addSetMethods(clazz);
        // 查找并记录所有字段（补充 getter/setter 缺失的属性）
        addFields(clazz);
        // 初始化可读属性名数组（有 getter 方法或可直接访问字段的属性名）
        readablePropertyNames = getMethods.keySet().toArray(new String[0]);
        // 初始化可写属性名数组（有 setter 方法或可直接访问字段的属性名）
        writablePropertyNames = setMethods.keySet().toArray(new String[0]);
        // 构建属性名（大写）到实际属性名的映射，实现属性名大小写不敏感查找
        for (String propName : readablePropertyNames) {
            // 将可读属性名转为大写后作为 key，实际属性名作为 value 存入映射
            caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
        }
        for (String propName : writablePropertyNames) {
            // 将可写属性名转为大写后作为 key，实际属性名作为 value 存入映射
            caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
        }
    }

    /**
     * 查找并记录无参构造方法。
     * 该方法会查找传入类 clazz 的所有构造方法，如果存在无参数的构造方法（即默认构造方法），就将其赋值给 defaultConstructor 字段，方便后续实例化对象时使用。
     *
     * @param clazz 目标类
     */
    private void addDefaultConstructor(Class<?> clazz) {
        // 获取 clazz 类声明的所有构造方法（包括私有、保护、默认、公共）
        Constructor<?>[] constructors = clazz.getDeclaredConstructors();
        // 使用流（Stream）遍历所有构造方法，筛选出参数个数为0的构造方法（即无参构造方法）
        Arrays.stream(constructors)
                .filter(constructor -> constructor.getParameterTypes().length == 0) // 只保留无参构造方法
                .findAny() // 找到任意一个无参构造方法（如果有的话）
                .ifPresent(constructor -> this.defaultConstructor = constructor); // 如果找到了，就赋值给 defaultConstructor 字段
    }

    /**
     * 查找所有 getter 方法，并处理冲突。
     * 该方法会遍历目标类的所有方法，筛选出符合 getter 规范的方法（无参数且方法名以 get/is 开头），
     * 然后将这些方法按属性名分组，最后解决同一属性名下可能存在的 getter 冲突（如重载、返回类型不同等）。
     *
     * @param clazz 目标类
     */
    private void addGetMethods(Class<?> clazz) {
        // 用于存储属性名与其对应的所有 getter 方法列表（可能有重载或冲突）
        Map<String, List<Method>> conflictingGetters = new HashMap<>();
        // 获取目标类及其父类、接口的所有方法
        Method[] methods = getClassMethods(clazz);
        // 遍历所有方法，筛选出无参数且是 getter 的方法
        Arrays.stream(methods)
                .filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
                // 将方法按属性名分组，加入冲突列表
                .forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m));
        // 解决每个属性名下的 getter 冲突，选出最终的 getter 方法
        resolveGetterConflicts(conflictingGetters);
    }

    /**
     * 解决 getter 方法冲突（如重载、返回类型不同等）
     * 例如：同一个属性名可能有多个 getter 方法（如 getX() 和 isX()），需要选出最合适的一个。
     * 规则如下：
     * 1. 如果只有一个方法，直接选它。
     * 2. 如果有多个，优先选返回类型更具体的（子类优先）。
     * 3. 如果返回类型一样且是 boolean，优先 isX()。
     * 4. 如果无法判断，标记为歧义（ambiguous）。
     *
     * @param conflictingGetters 属性名到其所有 getter 方法列表的映射
     */
    private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
        // 遍历每个属性名及其对应的所有 getter 方法列表
        for (Map.Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
            Method winner = null; // 最终选中的 getter 方法
            String propName = entry.getKey(); // 属性名
            boolean isAmbiguous = false; // 是否存在歧义
            // 遍历该属性名下的所有 getter 方法
            for (Method candidate : entry.getValue()) {
                if (winner == null) {
                    // 第一个方法，先作为候选
                    winner = candidate;
                    continue;
                }
                Class<?> winnerType = winner.getReturnType(); // 当前候选方法的返回类型
                Class<?> candidateType = candidate.getReturnType(); // 新方法的返回类型
                if (candidateType.equals(winnerType)) {
                    // 返回类型相同
                    if (!boolean.class.equals(candidateType)) {
                        // 不是 boolean 类型，存在歧义
                        isAmbiguous = true;
                        break;
                    } else if (candidate.getName().startsWith("is")) {
                        // 如果是 boolean 类型，且新方法名以 is 开头，优先选它
                        winner = candidate;
                    }
                } else if (candidateType.isAssignableFrom(winnerType)) {
                    // winnerType 是 candidateType 的子类，winner 优先，不做更换
                } else if (winnerType.isAssignableFrom(candidateType)) {
                    // candidateType 是 winnerType 的子类，candidate 优先，替换 winner
                    winner = candidate;
                } else {
                    // 两个返回类型无继承关系，存在歧义
                    isAmbiguous = true;
                    break;
                }
            }
            // 将最终选中的 getter 方法加入映射表，如果有歧义则特殊处理
            addGetMethod(propName, winner, isAmbiguous);
        }
    }

    /**
     * 将 getter 方法添加到映射表中
     *
     * @param name        属性名
     * @param method      getter 方法
     * @param isAmbiguous 是否存在歧义（如有多个返回类型相同的 getter 方法）
     */
    private void addGetMethod(String name, Method method, boolean isAmbiguous) {
        // 如果存在歧义，则使用 AmbiguousMethodInvoker 包装方法，否则用普通的 MethodInvoker
        MethodInvoker invoker = isAmbiguous
                ? new AmbiguousMethodInvoker(
                method,
                MessageFormat.format(
                        // 构造歧义提示信息
                        "Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results.",
                        name, method.getDeclaringClass().getName()
                ))
                : new MethodInvoker(method); // 没有歧义，直接用 MethodInvoker 包装
        // 将属性名和 invoker 放入 getMethods 映射表，后续可通过属性名快速获取 getter 调用器
        getMethods.put(name, invoker);
        // 解析 getter 方法的返回类型（支持泛型），得到 Type 类型
        Type returnType = TypeParameterResolver.resolveReturnType(method, type);
        // 将属性名和返回类型的 Class 放入 getTypes 映射表，便于后续类型判断
        getTypes.put(name, typeToClass(returnType));
    }

    /**
     * 查找所有 setter 方法，并处理冲突。
     * 本方法会遍历目标类的所有方法，筛选出符合 setter 规范的方法（即只有一个参数且方法名以 set 开头），
     * 然后将这些方法按属性名分组，最后解决同一属性名下可能存在的 setter 冲突（如重载、参数类型不同等）。
     *
     * @param clazz 目标类
     */
    private void addSetMethods(Class<?> clazz) {
        // 用于存储属性名与其对应的所有 setter 方法列表（可能有重载或冲突）
        Map<String, List<Method>> conflictingSetters = new HashMap<>();
        // 获取目标类及其父类、接口的所有方法
        Method[] methods = getClassMethods(clazz);
        // 遍历所有方法，筛选出只有一个参数且是 setter 的方法
        Arrays.stream(methods)
                .filter(m -> m.getParameterTypes().length == 1 && PropertyNamer.isSetter(m.getName()))
                // 将方法按属性名分组，加入冲突列表
                .forEach(m -> addMethodConflict(conflictingSetters, PropertyNamer.methodToProperty(m.getName()), m));
        // 解决每个属性名下的 setter 冲突，选出最终的 setter 方法
        resolveSetterConflicts(conflictingSetters);
    }

    /**
     * 将方法加入到冲突方法列表。
     *
     * @param conflictingMethods 属性名到方法列表的映射（用于记录有冲突的方法）
     * @param name               属性名
     * @param method             方法对象
     */
    private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {
        // 判断属性名是否合法（排除特殊字段，如$开头、serialVersionUID、class等）
        if (isValidPropertyName(name)) {
            // 如果属性名已存在，则获取对应的方法列表；否则新建一个空列表
            List<Method> list = MapUtil.computeIfAbsent(conflictingMethods, name, k -> new ArrayList<>());
            // 将当前方法加入到该属性名对应的方法列表中
            list.add(method);
        }
    }

    /**
     * 解决 setter 方法冲突（如重载、参数类型不同等）
     * 例如：同一个属性名可能有多个 setter 方法（如 setX(int) 和 setX(String)），需要选出最合适的一个。
     * 规则如下：
     * 1. 如果 getter 存在且类型和 setter 参数类型完全一致，优先选这个 setter。
     * 2. 如果没有完全一致的，就在所有 setter 里挑一个最合适的（比如参数类型更具体的）。
     * 3. 如果无法判断（比如参数类型无继承关系），则标记为歧义。
     *
     * @param conflictingSetters 属性名到其所有 setter 方法列表的映射
     */
    private void resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) {
        // 遍历每个属性名及其对应的所有 setter 方法列表
        for (Map.Entry<String, List<Method>> entry : conflictingSetters.entrySet()) {
            String propName = entry.getKey(); // 属性名
            List<Method> setters = entry.getValue(); // 该属性名下的所有 setter 方法
            Class<?> getterType = getTypes.get(propName); // 对应 getter 的返回类型
            boolean isGetterAmbiguous = getMethods.get(propName) instanceof AmbiguousMethodInvoker; // getter 是否有歧义
            boolean isSetterAmbiguous = false; // setter 是否有歧义
            Method match = null; // 最终选中的 setter 方法
            // 遍历所有 setter 方法，选出最合适的
            for (Method setter : setters) {
                // 如果 getter 没有歧义，且 setter 参数类型和 getter 返回类型完全一致，优先选这个
                if (!isGetterAmbiguous && setter.getParameterTypes()[0].equals(getterType)) {
                    match = setter;
                    break; // 找到完全匹配的就直接退出循环
                }
                // 如果还没发现歧义，就继续比较，挑出更合适的 setter
                if (!isSetterAmbiguous) {
                    match = pickBetterSetter(match, setter, propName); // 比较当前 match 和新的 setter
                    isSetterAmbiguous = match == null; // 如果返回 null，说明有歧义
                }
            }
            // 如果最终选出了合适的 setter 方法，就添加到映射表
            if (match != null) {
                addSetMethod(propName, match);
            }
            // 如果 match 为 null，说明有歧义，pickBetterSetter 已经处理了歧义情况
        }
    }

    /**
     * 比较两个 setter 方法，选出更合适的
     *
     * @param setter1  第一个 setter 方法（可能为 null）
     * @param setter2  第二个 setter 方法
     * @param property 属性名
     * @return 返回更合适的 setter 方法，如果有歧义则返回 null
     */
    private Method pickBetterSetter(Method setter1, Method setter2, String property) {
        // 如果第一个 setter 为空，直接返回第二个
        if (setter1 == null) {
            return setter2;
        }
        // 获取第一个 setter 的参数类型
        Class<?> paramType1 = setter1.getParameterTypes()[0];
        // 获取第二个 setter 的参数类型
        Class<?> paramType2 = setter2.getParameterTypes()[0];
        // 如果 paramType1 是 paramType2 的父类或接口，优先选择更具体的 paramType2
        if (paramType1.isAssignableFrom(paramType2)) {
            return setter2;
            // 如果 paramType2 是 paramType1 的父类或接口，优先选择更具体的 paramType1
        } else if (paramType2.isAssignableFrom(paramType1)) {
            return setter1;
        }
        // 如果两个参数类型没有继承关系，视为歧义
        // 创建一个歧义的 setter 方法调用器，包装 setter1，并记录歧义信息
        MethodInvoker invoker = new AmbiguousMethodInvoker(setter1,
                MessageFormat.format(
                        // 构造歧义提示信息，包含属性名、类名、两个参数类型
                        "Ambiguous setters defined for property ''{0}'' in class ''{1}'' with types ''{2}'' and ''{3}''.",
                        property, setter2.getDeclaringClass().getName(), paramType1.getName(), paramType2.getName()));
        // 将歧义的 setter 方法放入 setMethods 映射表，后续通过属性名查找时会发现歧义
        setMethods.put(property, invoker);
        // 解析 setter1 的参数类型（支持泛型），并存入 setTypes 映射表
        Type[] paramTypes = TypeParameterResolver.resolveParamTypes(setter1, type);
        setTypes.put(property, typeToClass(paramTypes[0]));
        // 返回 null，表示有歧义，无法确定唯一的 setter
        return null;
    }

    /**
     * 将 setter 方法添加到 setMethods 和 setTypes 映射表中
     *
     * @param name   属性名
     * @param method setter 方法对象
     */
    private void addSetMethod(String name, Method method) {
        // 用 MethodInvoker 包装 setter 方法，便于后续通过反射调用
        MethodInvoker invoker = new MethodInvoker(method);
        // 将属性名和 invoker 放入 setMethods 映射表，后续可通过属性名快速获取 setter 调用器
        setMethods.put(name, invoker);
        // 解析 setter 方法的参数类型（支持泛型），得到 Type 类型数组
        Type[] paramTypes = TypeParameterResolver.resolveParamTypes(method, type);
        // 将属性名和参数类型的 Class 放入 setTypes 映射表，便于后续类型判断
        setTypes.put(name, typeToClass(paramTypes[0]));
    }

    /**
     * 将 Type 类型转换为 Class 类型。
     * 这个方法用于处理 Java 反射中的各种类型（如普通类、泛型、数组等），
     * 返回对应的 Class 对象，便于后续类型判断和反射操作。
     *
     * @param src 需要转换的 Type 对象
     * @return 对应的 Class 对象，如果无法确定则返回 Object.class
     */
    private Class<?> typeToClass(Type src) {
        Class<?> result = null; // 最终要返回的 Class 类型，初始为 null
        if (src instanceof Class) {
            // 如果 src 本身就是 Class 类型，直接强转返回
            result = (Class<?>) src;
        } else if (src instanceof ParameterizedType) {
            // 如果 src 是带泛型的类型（如 List<String>），取其原始类型（如 List）
            result = (Class<?>) ((ParameterizedType) src).getRawType();
        } else if (src instanceof GenericArrayType) {
            // 如果 src 是泛型数组类型（如 T[]），需要递归获取其组件类型的 Class
            Type componentType = ((GenericArrayType) src).getGenericComponentType();
            if (componentType instanceof Class) {
                // 如果组件类型是 Class，直接创建一个该类型的空数组并获取其 Class
                result = Array.newInstance((Class<?>) componentType, 0).getClass();
            } else {
                // 如果组件类型不是 Class，递归调用 typeToClass 获取组件类型的 Class
                Class<?> componentClass = typeToClass(componentType);
                // 创建该组件类型的空数组并获取其 Class
                result = Array.newInstance(componentClass, 0).getClass();
            }
        }
        if (result == null) {
            // 如果以上都不是，无法确定类型，默认返回 Object.class
            result = Object.class;
        }
        return result; // 返回最终的 Class 类型
    }

    /**
     * 递归查找所有字段，补充 getter/setter 缺失的属性。
     * 这个方法会遍历传入类 clazz 及其所有父类的所有字段（包括私有字段），
     * 如果某个字段没有对应的 setter/getter 方法，则为它补充字段级的 Invoker（反射调用器）。
     *
     * @param clazz 目标类
     */
    private void addFields(Class<?> clazz) {
        // 获取 clazz 声明的所有字段（不包括父类字段）
        Field[] fields = clazz.getDeclaredFields();
        // 遍历每一个字段
        for (Field field : fields) {
            // 如果 setMethods（setter方法或字段写入器）中没有该字段名
            if (!setMethods.containsKey(field.getName())) {
                // 获取字段的修饰符（如 public、private、final、static 等）
                int modifiers = field.getModifiers();
                // 如果该字段不是 final 且不是 static（final static 字段不能通过反射设置）
                if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
                    // 为该字段添加字段写入器（SetFieldInvoker）
                    addSetField(field);
                }
            }
            // 如果 getMethods（getter方法或字段读取器）中没有该字段名
            if (!getMethods.containsKey(field.getName())) {
                // 为该字段添加字段读取器（GetFieldInvoker）
                addGetField(field);
            }
        }
        // 如果 clazz 有父类（不是 Object），递归处理父类的字段
        if (clazz.getSuperclass() != null) {
            addFields(clazz.getSuperclass());
        }
    }

    /**
     * 添加字段写入器（即为没有 setter 方法的字段，提供通过反射直接赋值的能力）。
     *
     * @param field 需要添加写入器的字段对象
     */
    private void addSetField(Field field) {
        // 判断字段名是否合法（排除以 $ 开头、serialVersionUID、class 等特殊字段）
        if (isValidPropertyName(field.getName())) {
            // 将字段名和对应的 SetFieldInvoker（字段写入器）放入 setMethods 映射表
            // SetFieldInvoker 用于通过反射直接给字段赋值
            setMethods.put(field.getName(), new SetFieldInvoker(field));
            // 解析字段的类型（支持泛型），得到 Type 类型
            Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
            // 将字段名和字段类型的 Class 放入 setTypes 映射表，便于后续类型判断
            setTypes.put(field.getName(), typeToClass(fieldType));
        }
    }

    /**
     * 添加字段读取器（为没有 getter 方法的字段，提供通过反射直接读取字段值的能力）。
     *
     * @param field 需要添加读取器的字段对象
     */
    private void addGetField(Field field) {
        // 判断字段名是否合法（排除以 $ 开头、serialVersionUID、class 等特殊字段）
        if (isValidPropertyName(field.getName())) {
            // 将字段名和对应的 GetFieldInvoker（字段读取器）放入 getMethods 映射表
            // GetFieldInvoker 用于通过反射直接获取字段的值
            getMethods.put(field.getName(), new GetFieldInvoker(field));
            // 解析字段的类型（支持泛型），得到 Type 类型
            Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
            // 将字段名和字段类型的 Class 放入 getTypes 映射表，便于后续类型判断
            getTypes.put(field.getName(), typeToClass(fieldType));
        }
    }

    /**
     * 判断属性名是否合法（排除特殊字段）。
     * 该方法用于判断传入的属性名是否是有效的普通属性名。
     * 它会排除掉以 $ 开头的名字、serialVersionUID 和 class 这三种特殊名字。
     * 这样做的目的是避免对 Java 内部字段或特殊用途字段进行反射操作。
     *
     * @param name 属性名字符串
     * @return 如果是普通属性名返回 true，否则返回 false
     */
    private boolean isValidPropertyName(String name) {
        // 如果属性名以 $ 开头，或者等于 serialVersionUID，或者等于 class，则返回 false（不是有效属性名）
        // 否则返回 true（是有效属性名）
        return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));
    }

    /**
     * 获取类及其父类、接口的所有方法（包括私有方法）。
     * 这个方法会递归查找传入类 clazz 及其所有父类、接口的所有方法（包括私有方法），
     * 并去重（同签名只保留一个，优先子类），最终返回所有方法的数组。
     *
     * @param clazz 需要分析的类
     * @return 该类及其父类、接口的所有方法（去重后）
     */
    private Method[] getClassMethods(Class<?> clazz) {
        // 用于存储所有唯一的方法，key 是方法签名，value 是方法对象
        Map<String, Method> uniqueMethods = new HashMap<>();
        // 当前正在处理的类，初始为传入的 clazz
        Class<?> currentClass = clazz;
        // 循环处理当前类及其所有父类，直到 Object 类为止
        while (currentClass != null && currentClass != Object.class) {
            // 把当前类声明的所有方法（包括私有方法）加入 uniqueMethods，去重
            addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
            // 还要处理当前类实现的所有接口的方法（接口方法都是 public）
            Class<?>[] interfaces = currentClass.getInterfaces();
            for (Class<?> anInterface : interfaces) {
                // 把接口的所有方法也加入 uniqueMethods，去重
                addUniqueMethods(uniqueMethods, anInterface.getMethods());
            }
            // 继续处理父类
            currentClass = currentClass.getSuperclass();
        }
        // uniqueMethods.values() 是所有去重后的 Method 对象集合
        Collection<Method> methods = uniqueMethods.values();
        // 转为 Method 数组返回
        return methods.toArray(new Method[0]);
    }

    /**
     * 向 uniqueMethods 添加不重复的方法（签名唯一）。
     * 这个方法的作用是：遍历传入的 methods 数组，把每个方法根据其“签名”加入 uniqueMethods 映射表中。
     * 如果已经有同样签名的方法（比如父类和子类有同名同参方法），只保留第一个遇到的（通常是子类的）。
     *
     * @param uniqueMethods 已有的唯一方法映射（key 是方法签名，value 是方法对象）
     * @param methods       需要处理的方法数组
     */
    private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
        // 遍历所有方法
        for (Method currentMethod : methods) {
            // 跳过桥接方法（桥接方法是 Java 编译器为泛型等生成的特殊方法，通常不需要处理）
            if (!currentMethod.isBridge()) {
                // 获取当前方法的签名字符串（如：返回类型#方法名:参数类型1,参数类型2...）
                String signature = getSignature(currentMethod);
                // 如果 uniqueMethods 中还没有这个签名的方法，说明是第一次遇到，加入映射表
                if (!uniqueMethods.containsKey(signature)) {
                    uniqueMethods.put(signature, currentMethod);
                }
                // 如果已经有同签名方法，说明子类覆盖了父类方法，跳过即可
            }
        }
    }

    /**
     * 生成方法签名字符串（格式为：返回类型#方法名:参数类型1,参数类型2...）。
     * 这个签名用于唯一标识一个方法，便于方法去重和查找。
     *
     * @param method 方法对象
     * @return 方法签名字符串
     */
    private String getSignature(Method method) {
        // 创建一个可变字符串，用于拼接签名
        StringBuilder sb = new StringBuilder();
        // 获取方法的返回类型
        Class<?> returnType = method.getReturnType();
        // 如果返回类型不为 null
        if (returnType != null) {
            // 追加返回类型的全限定名和 '#' 分隔符
            sb.append(returnType.getName()).append('#');
        }
        // 追加方法名
        sb.append(method.getName());
        // 获取方法的所有参数类型
        Class<?>[] parameters = method.getParameterTypes();
        // 遍历每一个参数类型
        for (int i = 0; i < parameters.length; i++) {
            // 第一个参数前加 ':'，后续参数前加 ','，再追加参数类型的全限定名
            sb.append(i == 0 ? ':' : ',').append(parameters[i].getName());
        }
        // 返回拼接好的方法签名字符串
        return sb.toString();
    }

    /**
     * 检查当前环境是否允许通过反射机制修改成员的可访问性（如 setAccessible(true)）
     *
     * @return true 表示可以，false 表示不允许
     */
    public static boolean canControlMemberAccessible() {
        try {
            SecurityManager securityManager = System.getSecurityManager();
            if (null != securityManager) {
                securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
            }
        } catch (SecurityException e) {
            return false;
        }
        return true;
    }

    /**
     * 获取目标类的 Class 对象
     */
    public Class<?> getType() {
        return type;
    }

    /**
     * 获取无参构造方法
     */
    public Constructor<?> getDefaultConstructor() {
        if (defaultConstructor != null) {
            return defaultConstructor;
        } else {
            throw new RuntimeException("There is no default constructor for " + type);
        }
    }

    /**
     * 是否有无参构造方法
     */
    public boolean hasDefaultConstructor() {
        return defaultConstructor != null;
    }

    /**
     * 获取属性的 setter 调用器
     */
    public Invoker getSetInvoker(String propertyName) {
        Invoker method = setMethods.get(propertyName);
        if (method == null) {
            throw new RuntimeException("There is no setter for property named '" + propertyName + "' in '" + type + "'");
        }
        return method;
    }

    /**
     * 获取属性的 getter 调用器
     */
    public Invoker getGetInvoker(String propertyName) {
        Invoker method = getMethods.get(propertyName);
        if (method == null) {
            throw new RuntimeException("There is no getter for property named '" + propertyName + "' in '" + type + "'");
        }
        return method;
    }

    /**
     * 获取属性 setter 的参数类型
     */
    public Class<?> getSetterType(String propertyName) {
        Class<?> clazz = setTypes.get(propertyName);
        if (clazz == null) {
            throw new RuntimeException("There is no setter for property named '" + propertyName + "' in '" + type + "'");
        }
        return clazz;
    }

    /**
     * 获取属性 getter 的返回类型
     */
    public Class<?> getGetterType(String propertyName) {
        Class<?> clazz = getTypes.get(propertyName);
        if (clazz == null) {
            throw new RuntimeException("There is no getter for property named '" + propertyName + "' in '" + type + "'");
        }
        return clazz;
    }

    /**
     * 获取所有可读属性名
     */
    public String[] getGetablePropertyNames() {
        return readablePropertyNames;
    }

    /**
     * 获取所有可写属性名
     */
    public String[] getSetablePropertyNames() {
        return writablePropertyNames;
    }

    /**
     * 判断是否有指定属性的 setter
     */
    public boolean hasSetter(String propertyName) {
        return setMethods.containsKey(propertyName);
    }

    /**
     * 判断是否有指定属性的 getter
     */
    public boolean hasGetter(String propertyName) {
        return getMethods.containsKey(propertyName);
    }

    /**
     * 根据属性名（不区分大小写）查找实际属性名
     */
    public String findPropertyName(String name) {
        return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));
    }
}
